package com.warmlight.voicepacket.service;

import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.text.TextUtils;

import com.warmlight.voicepacket.common.Constants;
import com.warmlight.voicepacket.utils.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * Created by weiweijinpeng on 2018/8/6.
 */

public class DownLoadVideoService extends Service {

    private DownLoadPool downLoadPool;
    private LinkedHashMap<String,MultimediaInfo> allTaskList;
    private HashMap<String,DownloadThread> allThreadList;

    private final int DOWNLOADING = 0;              /** 下载 */
    private final int WAITING = 1;                  /** 等待 */
    private final int PAUSED = 2;                   /** 暂停 */
    private final int FAILED = 3;                   /** 失败 */

    static final int MAX_DOWNLOADING_TASK = 1;      /** 最大同时下载数 */
    private int runningThread = 0;


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        if(downLoadPool == null){
            downLoadPool = new DownLoadPool(MAX_DOWNLOADING_TASK);
        }
        if(allTaskList == null){                //创建任务集合
            allTaskList = new LinkedHashMap<>();
        }
        if(allThreadList == null){              //创建线程集合
            allThreadList = new HashMap<>();
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        File videoFile = new File(Constants.CALL_PICTURE_FILE_PATH);
        if (!videoFile.exists()) {
            videoFile.mkdirs();
        }
        //检测传过来的请求是否完整
        if (intent != null && intent.getAction() != null && intent.getAction().equals("NewVideoTask")){
            Bundle bundle = intent.getExtras();
            if(bundle != null){
                MultimediaInfo info = (MultimediaInfo) bundle.get("MediaInfo");
                if(info != null){
                    checkTask(info);
                }
            }
        }
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 检查新的下载任务
     * @param info  媒体信息
     */
    private synchronized void checkTask(MultimediaInfo info){
        if (info != null){
            //检查是否存在同名的文件
            String videoUrl = info.getVideoUrl();
            File file = new File(info.getVideoPath());
            if (file.exists()){
            }else {
                startTask(info);
            }
        }
    }

    /**
     * 将任务添加到下载队列中
     * @param info  媒体信息
     */
    private void startTask(MultimediaInfo info){
        // 如果当前还有空闲的位置则直接下载，否则就是在等待中
        if (runningThread < MAX_DOWNLOADING_TASK){
            runningThread ++;
            info.setDownStatus(DOWNLOADING);
            String videoUrl = info.getVideoUrl();
            DownloadThread thread = new DownloadThread(info);
            downLoadPool.submit(new FutureTask<>(thread),videoUrl);
            allThreadList.put(videoUrl,thread);    //任务存起来，便于单独操作
        }else {
        }
    }

    /**
     * 删除任务
     * */
    public void deleteTask(String videoUrl){
        if(allTaskList.containsKey(videoUrl)){
            allTaskList.remove(videoUrl);
        }
        if(allThreadList.containsKey(videoUrl)){
            allThreadList.remove(videoUrl);
            runningThread -= 1;
        }
        downLoadPool.removeTag(videoUrl);
    }

    /**
     * 下载线程
     * */
    private class DownloadThread implements Callable<String> {

        private MultimediaInfo info;              /** 文件信息 */
        private File downloadFile;              /** 文件下载路径 */
        private String tmpFileSize;             /** 临时文件大小 */

        private String videoUrl;
        private String videoPath;

        DownloadThread(MultimediaInfo info) {
            this.info = info;
            this.videoUrl = info.getVideoUrl();
            this.videoPath = info.getVideoPath();
        }

        @Override
        public String call() throws Exception {
            downloadFile = new File(videoPath + ".tmp");
            //先检查是否有之前的临时文件
            if (downloadFile.exists()){
                tmpFileSize = "bytes=" + downloadFile.length() + "-";
            }
            //创建 OkHttp 对象相关
            OkHttpClient client = new OkHttpClient();
            //如果有临时文件,则在下载的头中添加下载区域
            Request request;
            if ( !TextUtils.isEmpty(tmpFileSize) ){
                request = new Request.Builder().url(videoUrl).header("Range",tmpFileSize).build();
            }else {
                request = new Request.Builder().url(videoUrl).build();
            }
            Call call = client.newCall(request);
            try {
                // 读写文件
                bytes2File(call);
            } catch (IOException e) {
                deleteTask(videoUrl);       //出现异常则删除任务 一般为网络异常
                return null;
            }
            onCompleted();
            return null;
        }

        /**
         * 将下载的数据存到本地文件
         * @param call  OkHttp的Call对象
         * @throws IOException  下载的异常
         */
        private void bytes2File(Call call) throws IOException {
            //设置输出流
            OutputStream outPutStream;
            //检测是否支持断点续传
            Response response = call.execute();
            ResponseBody responseBody = response.body();
            String responseRange = response.headers().get("Content-Range");
            //最后的标记为true 表示下载的数据可以从上一次的位置写入,否则会清空文件数据
            if (responseRange == null || !responseRange.contains(Long.toString(downloadFile.length()))){
                outPutStream = new FileOutputStream(downloadFile,false);
            }else {
                outPutStream = new FileOutputStream(downloadFile,true);
            }
            InputStream inputStream = responseBody.byteStream();

            //如果有下载过的历史文件，则把下载总大小设为，总数据大小+文件大小，否则就是总数据大小
            if (TextUtils.isEmpty(tmpFileSize)){
                info.setTotalSize(responseBody.contentLength());
            }else {
                info.setTotalSize(responseBody.contentLength() + downloadFile.length());
            }

            //设置缓存大小 写入文件
            int length;
            byte[] buffer = new byte[1024];
            while ((length = inputStream.read(buffer)) != -1){
                outPutStream.write(buffer,0,length);
                onDownload(downloadFile.length());
            }

            /** 清空缓冲区 */
            outPutStream.flush();
            outPutStream.close();
            inputStream.close();
        }

        /**
         * 当产生下载进度时
         * @param downloadedSize    当前下载的数据大小
         */
        int i = 0;
        boolean flag = true;
        private void onDownload(long downloadedSize) {
            info.setDownSize(downloadedSize);
            long totalSize = info.getTotalSize();
            int progress = (int) (((float)  downloadedSize / totalSize) * 100);
            if(flag && progress != 0){
                i = progress;
            }
            if(flag){ flag = false; }
            if(progress > i){       //避免频繁更新 一个百分点更新一次
                i += 1;
            }
        }

        /** 下载完成 */
        private void onCompleted(){

            //当前下载数减一
            runningThread --;
            //将临时文件名更改回正式文件名
            boolean rename = downloadFile.renameTo(new File(videoPath));

            //保存到手机相册
            Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            Uri uri = Uri.fromFile(new File(videoPath));
            intent.setData(uri);
            sendBroadcast(intent);

            if(rename){
            }else {
            }
            //移除下载信息
            allTaskList.remove(videoUrl);
            allThreadList.remove(videoUrl);
            downLoadPool.removeTag(videoUrl);
        }
    }

    /**
     * 查找一个等待中的任务
     * @return  查找到的任务信息info , 没有则返回 Null
     */
    private synchronized MultimediaInfo startNextTask(){
        for (MultimediaInfo info : allTaskList.values()) {
            if (info.getDownStatus() == WAITING) {
                //在找到等待中的任务之后,我们先把它的状态设置成 暂停 ,再进行创建
                info.setDownStatus(PAUSED);
                return info;
            }
        }
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        downLoadPool.shutdown();
    }

}
